﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WCAD.Kean
{
    public class GetTextVectors
    {
        //https://www.keanw.com/2014/01/exploding-autocad-text-and-manipulating-the-results-using-net.html
        private ObjectIdCollection _entIds;
        [CommandMethod("EXPVECS")]
        public void ExplodeToVectors()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            _entIds = new ObjectIdCollection();
            var pso = new PromptSelectionOptions();
            pso.MessageForAdding = "Select text objects to explode";
            var psr = ed.GetSelection(pso);
            if (psr.Status != PromptStatus.OK) return;
            // Pass the objects to explode via the pickfirst selection
            // set and save them to be unerased in the next command
            var origIds = psr.Value.GetObjectIds();
            var msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
            // We're going to copy the original text entities and then
            // pass the copies into TXTEXP, which will then go and erase
            // them, leaving the originals intact
            // If you want the originals erased, just pass origIds into
            // the call to SetImpliedSelection() and delete the lines
            // of code prior to it
            var map = new IdMapping();
            db.DeepCloneObjects(new ObjectIdCollection(origIds), msId, map, false);
            // Use a handy LINQ "map" to extract the ObjectId of the copy
            // for each of the input IDs
            var copiedIds =(from id in origIds select map[id].Value).ToArray<ObjectId>();
            ed.SetImpliedSelection(copiedIds);
            // We'll use COM's SendCommand, but using InvokeMember()
            // on the type rather than using the TypeLib
            var odoc = doc.GetAcadDocument();
            var docType = odoc.GetType();
            // Check for objects added to the database
            db.ObjectAppended += new ObjectEventHandler(ObjectAppended);
            // Call SendCommand passing in both the Express Tools'
            // TXTEXP command and then the custom TXTFIX command
            // to fix the results
            //var args = new object[] { "TXTEXP\nTXTFIX\n" };
            //docType.InvokeMember(
            //  "SendCommand", BindingFlags.InvokeMethod, null, odoc, args
            //);
            // Actually, no. I've switched back to SendStringToExecute,
            // as in any case the mode we're using is asynchronous
            doc.SendStringToExecute("TXTEXP\nTXTFIX\n", false, false, false);
        }

        [CommandMethod("TXTFIX", CommandFlags.NoHistory)]
        public void FixText()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            // Remove the event handler
            db.ObjectAppended -= new ObjectEventHandler(ObjectAppended);
            if (_entIds.Count == 0)
            {
                ed.WriteMessage("\nCould not find any entities created by TXTEXP.");
                return;
            }
            // To show we can, let's change the colour of each of
            // the entities generated by TXTEXP to red
            using (var tr = doc.TransactionManager.StartTransaction())
            {
                foreach (ObjectId id in _entIds)
                {
                    // TXTEXP erases quite a few temporary objects, so be
                    // sure to check their erased status first
                    if (!id.IsErased)
                    {
                        var ent = (Entity)tr.GetObject(id, OpenMode.ForWrite);
                        ent.ColorIndex = 1;
                    }
                }
                tr.Commit();
            }
        }
        void ObjectAppended(object sender, ObjectEventArgs e)
        {
            if (e.DBObject is Entity)
            {
                _entIds.Add(e.DBObject.ObjectId);
            }
        }
    }
}
